﻿// --- Copyright (c) 2010 Steven Hartgers ---
// Copyright (C) 2010 Steven Hartgers All rights are reserved.
// Author contact: fiinix00/at\gmail.com
// ------------------------------------------------------------------------
// This program is free software: you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation, either version 3 of the License, or 
// (at your option) any later version. 
//  
// This program is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more detail
//  
// You should have received a copy of the GNU General Public License 
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
// ------------------------------------------------------------------------
// COPYRIGHT NOTICE: This copyright notice may NOT be removed, obscured or modified 
// without written consent from the author.
// --- End copyright notice --- 


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hack.Extensions;
using System.Reflection;
using Hack.Attributes;
namespace Hack.Numbers.Bytes
{
    /*
    1000	k	kilo
    10002	M	mega
    10003	G	giga
    10004	T	tera
    10005	P	peta
    10006	E	exa
    10007	Z	zetta
    10008	Y	yotta             


    bytes / 1024 == KB
    bytes / 1024^2 == MB
    bytes / 1024^3 == GB
    bytes / 1024^4 == TB
    */


    public static class BytesExtension
    {
        public static ByteType ConvertTo<ByteType>(this Bytes f)
            where ByteType : Bytes
        {
            var ToType = typeof(ByteType);
            var FromType = f.GetType();

            var IntBytes = f.IntBytes;

            BytePower orginalPower = FromType.GetAttribute<BytePower>();
            BytePower wantedPower = ToType.GetAttribute<BytePower>();
            Bytes WorkedType = null;
            if (orginalPower.Power < wantedPower.Power)
            {
                //orginal is smaler
                long workingarea = (long)orginalPower.Power / (long)wantedPower.Power;
                WorkedType = new Bytes(
                    // 1kb = 1024
                    // 1mb = 1024 * 1024kb // 1048576
                    IntBytes * workingarea
                );
            }
            else
            {
                //orginal is bigger
                ulong workingarea = orginalPower.Power / wantedPower.Power;
                WorkedType = new Bytes(
                   IntBytes * workingarea
                );
            }

            var bases = (ByteType)Activator.CreateInstance(ToType, new object[] { WorkedType });

            return (ByteType)bases;
        }
    }
    #region ByteTypes
    [BytePower(1)]
    public class Bytes
    {
        public double IntBytes { get; set; }
        public Bytes(Bytes bytes) : this(bytes.IntBytes) { }
        public Bytes(double bytes)
        {
            this.IntBytes = bytes;
        }
    }

    [BytePower(1024)]
    public class KiloByte : Bytes
    {
        [BytePower(1024)]
        public KiloByte(Bytes bytes)
            : base(bytes.IntBytes)
        {

        }
        public KiloByte(double bytes)
            : base(bytes)
        {

        }
    }
    [BytePower(1048576)]
    public class MegaByte : Bytes
    {
        [BytePower(1048576)]
        public MegaByte(Bytes bytes)
            : base(bytes.IntBytes)
        {

        }
        public MegaByte(double bytes)
            : base(bytes)
        {

        }
    }
    [BytePower(1073741824)]
    public class GigaByte : Bytes
    {
        public GigaByte(Bytes bytes)
            : base(bytes.IntBytes)
        {

        }
        public GigaByte(double bytes)
            : base(bytes)
        {

        }

    }
    [BytePower(1099511627776)]
    public class TerraByte : Bytes
    {
        public TerraByte(Bytes bytes)
            : base(bytes.IntBytes)
        {

        }
        public TerraByte(double bytes)
            : base(bytes)
        {

        }
    }
    [BytePower(1125899906842624)]
    public class ExtaByte : Bytes
    {
        public ExtaByte(Bytes bytes)
            : base(bytes.IntBytes)
        {

        }
        public ExtaByte(double bytes)
            : base(bytes)
        {

        }
    }
    [BytePower(1152921504606847000)]
    public class PetaByte : Bytes
    {
        public PetaByte(Bytes bytes)
            : base(bytes.IntBytes)
        {

        }
        public PetaByte(double bytes)
            : base(bytes)
        {

        }
    }
    #endregion


    //Compiler overflow...

    /*
    [BytePower(1.1805916207174113e+21)]
    public class ZettaByte : Bytes
    {
        public ZettaByte(Bytes bytes)
            : base(bytes.IntBytes)
        {

        }
    }
    [BytePower((int)System.Math.Pow(1024, 8))]
    public class YottaByte : Bytes
    {
        public YottaByte(Bytes bytes)
            : base(bytes.IntBytes)
        {

        }
    }
    */
}